<script setup>
import {nextTick, onMounted, reactive, ref, watch} from 'vue'
import request from '@/utils/request'
import {ElLoading, ElNotification} from 'element-plus'
import useSystemStore from '@/stores/system'
import router from '@/router'

import Register from '@/views/login/register.vue'
import Forget from '@/views/login/forgetpassword.vue'

import {Avatar} from "@element-plus/icons-vue";

const dialogVisible = ref(false)

// 相机拍照

const videoWidth = ref(710);

const videoHeight = ref(400);

const imgSrc = ref("");

const blobFile = ref(null);

const thisCancas = ref(null);

const thisContext = ref(null);

const thisVideo = ref(null);

const emit = defineEmits(["refreshDataList"]);

const $route = router
const systemStore = useSystemStore()
const formSize = ref('default')
const ruleFormRef = ref()
const captchaImg = ref()
const activeName = ref('first')
const ruleForm = reactive({
  username: '',
  password: '',
  code: '',
  token: '',
  face: ''
})
// 校验规则
const rules = reactive({
  username: [
    {required: true, message: '请输入账户名', trigger: 'blur'},
    {min: 5, max: 10, message: '账户名在5到10位', trigger: 'blur'}
  ],
  password: [
    {required: true, message: '请输入密码', trigger: 'blur'},
    {min: 5, max: 10, message: '密码在5到10位', trigger: 'blur'}
  ],
  code: [
    {required: true, message: '请输入验证码', trigger: 'blur'},
    {min: 5, max: 5, message: '验证码为长度为5', trigger: 'blur'}
  ]
})
//登录方法
const submitForm = async (formEl) => {
  if (!formEl) return
  formEl.validate(async (valid, fields) => {
    if (valid) {
      try {
        const res = await request.post('/auth/login', ruleForm)
        systemStore.setToken(res.data.tokenInfo.tokenValue)
        ElNotification({
          title: '登录成功',
          message: `${ruleForm.username} 欢迎您!`,
          type: 'success'
        })

        if (res.data.roleList.includes('user')) {
          $route.replace('/front')
        } else {
          $route.replace('/')
        }
      } catch (error) {
        getCaptcha()
      }
    }
  })
}
//重置方法
const resetForm = (formEl) => {
  if (!formEl) return
  formEl.resetFields()
  getCaptcha()
}
//获取验证码
const getCaptcha = async () => {
  const res = await request.get('/auth/captcha')

  captchaImg.value = res.data.captchaImg
  ruleForm.token = res.data.token
  ruleForm.code = ''
}
getCaptcha()
const handleFace = async () => {

  if (ruleForm.username.length < 5 || ruleForm.username.length > 10 || !ruleForm.username) {
    ElNotification({
      title: '提示',
      message: `账户名格式不正确`,
      type: 'warning'
    })
    return false
  }
  let synth = window.speechSynthesis;
  let utterThis = new SpeechSynthesisUtterance("请保持正对摄像头");
  synth.speak(utterThis);
  dialogVisible.value = true
  nextTick(() => {
    getCompetence()
  })
}
const getCompetence = () => {

  thisCancas.value = document.getElementById("canvasCamera");

  thisContext.value = thisCancas.value.getContext("2d");

  thisVideo.value = document.getElementById("videoCamera");

  // 旧版本浏览器可能根本不支持mediaDevices，我们首先设置一个空对象

  if (navigator.mediaDevices === undefined) {

    navigator.mediaDevices = {};

  }

  // 一些浏览器实现了部分mediaDevices，我们不能只分配一个对象

  // 使用getUserMedia，因为它会覆盖现有的属性。

  // 这里，如果缺少getUserMedia属性，就添加它。

  if (navigator.mediaDevices.getUserMedia === undefined) {

    navigator.mediaDevices.getUserMedia = function (constraints) {

      // 首先获取现存的getUserMedia(如果存在)

      let getUserMedia =

          navigator.webkitGetUserMedia ||

          navigator.mozGetUserMedia ||

          navigator.getUserMedia;

      // 有些浏览器不支持，会返回错误信息

      // 保持接口一致

      if (!getUserMedia) {

        return Promise.reject(
            new Error("getUserMedia is not implemented in this browser")
        );

      }

      // 否则，使用Promise将调用包装到旧的navigator.getUserMedia

      return new Promise(function (resolve, reject) {

        getUserMedia.call(navigator, constraints, resolve, reject);

      });

    };

  }

  let constraints = {

    audio: false,

    video: {

      width: videoWidth.value,

      height: videoHeight.value,

      transform: "scaleX(-1)",

    },

  };

  navigator.mediaDevices

      .getUserMedia(constraints)

      .then(function (stream) {


        if ("srcObject" in thisVideo.value) {

          thisVideo.value.srcObject = stream;

        } else {


          thisVideo.value.src = window.URL.createObjectURL(stream);

        }

        thisVideo.value.onloadedmetadata = function (e) {

          thisVideo.value.play();

        };

      })

      .catch((err) => {

        console.log(err);

      });

}
const setImage = async () => {


  thisContext.value.drawImage(
      thisVideo.value,

      0,

      0,

      videoWidth.value,

      videoHeight.value
  );


  let image = thisCancas.value.toDataURL("image/png");

  console.log(dataURLtoFile(image, "图片文件")); // 转换为file文件

  blobFile.value = dataURLtoFile(image, "图片文件");

  let formData = new FormData();

  formData.append("file", blobFile.value, "filename.jpg"); //图片内容


  console.log(formData.getAll("file")[0], "查看数据内容", formData); // 查看数据内容

  imgSrc.value = image;

  emit("refreshDataList", imgSrc.value);
  const loading = ElLoading.service({
    lock: true,
    text: '正在人脸比对',
    background: 'rgba(0, 0, 0, 0.7)',
  })
  // console.log("图片数据", imgSrc.value) ;
  try {
    const rem = await request.post(
        "/file/upload",
        formData
    );
    ruleForm.face = rem.data
    const res = await request.post(`/auth/facelogin`, ruleForm)
    systemStore.setToken(res.data.tokenInfo.tokenValue)
    ElNotification({
      title: '登录成功',
      message: `${ruleForm.username} 欢迎您!`,
      type: 'success'
    })
    let synth = window.speechSynthesis;

    let utterThis = new SpeechSynthesisUtterance(`登录成功，${ruleForm.username} 欢迎您使用人脸登录!`);
    synth.speak(utterThis);

    if (res.data.roleList.includes('user')) {
      $route.replace('/front')
    } else {
      $route.replace('/')
    }
    nextTick(() => {
      stopNavigator()
    })
    loading.close()
  } catch (e) {

    nextTick(() => {
      dialogVisible.value = false
      stopNavigator()
    })
    loading.close()
    let synth = window.speechSynthesis;

    let utterThis = new SpeechSynthesisUtterance(e);
    synth.speak(utterThis);


  }


};
const dataURLtoFile = (dataurl, filename) => {

  let arr = dataurl.split(",");

  let mime = arr[0].match(/:(.*?);/)[1];

  let bstr = atob(arr[1]);

  let n = bstr.length;

  let u8arr = new Uint8Array(n);

  while (n--) {

    u8arr[n] = bstr.charCodeAt(n);

  }

  return new File([u8arr], filename, {type: mime});

}
const stopNavigator = () => {

  thisVideo.value.srcObject.getTracks()[0].stop();

}
const handleClose = () => {

  dialogVisible.value = false

  nextTick(() => {

    stopNavigator()
  })
}

</script>

<template>
  <el-dialog style="width: 750px" :model-value="dialogVisible" title="请正对摄像头" :before-close="handleClose">

    <!-- poster="背景图" -->

    <video

        id="videoCamera"
        width="710"
        height="400"
        autoplay

    />

    <canvas

        style="display: none;margin: 0 auto"
        id="canvasCamera"
        :width="700"
        :height="400"

    ></canvas>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="handleClose">取消</el-button>
        <el-button @click="setImage()" type="primary">立即登录</el-button>
      </span>
    </template>
  </el-dialog>

  <div class="app_login">
    <div class="login_top">
      <img class="top_logo" src="public/logo.png"/>
      <p class="top_title">face-sign</p>
    </div>
    <div class="login_main">
      <el-row align="middle">

        <el-col :xs="24" :sm="14" :md="12" :lg="9" :xl="6">
          <div class="main_form">
            <el-card>
              <el-tabs v-model="activeName">
                <el-tab-pane label="密码登录" name="first">
                  <el-form
                      ref="ruleFormRef"
                      :model="ruleForm"
                      :rules="rules"
                      label-width="100px"
                      class="demo-ruleForm"
                      :size="formSize"
                      status-icon
                  >
                    <el-form-item label="账户名" prop="username">
                      <el-input v-model="ruleForm.username" prefix-icon="User"/>
                    </el-form-item>
                    <el-form-item label="密码" prop="password">
                      <el-input
                          v-model="ruleForm.password"
                          prefix-icon="Lock"
                          type="password"
                          show-password
                      />
                    </el-form-item>
                    <el-form-item label="验证码" prop="code">
                      <el-row align="middle">
                        <el-col :span="12">
                          <el-input v-model="ruleForm.code" prefix-icon="Crop"/>
                        </el-col>
                        <el-col :span="10" :offset="1"
                                style="display: flex; align-items: center">
                          <img
                              :src="captchaImg"
                              @click="getCaptcha"
                              style="border-radius: 3px 3px"
                          />
                        </el-col>
                      </el-row>
                    </el-form-item>

                    <br/>
                    <div style="display: flex; justify-content: center">

                      <el-button type="primary" @click="submitForm(ruleFormRef)"> 登录</el-button>
                      <el-button @click="resetForm(ruleFormRef)">重置</el-button>
                      <el-button type="warning" :icon="Avatar" circle
                                 @click="handleFace"></el-button>
                    </div>
                  </el-form>
                </el-tab-pane>


                <el-tab-pane label="注册" name="third">
                  <Register></Register>
                </el-tab-pane>
                <el-tab-pane label="忘记密码" name="four">
                  <Forget></Forget>
                </el-tab-pane>
              </el-tabs>

              <br/>
              <br/>
            </el-card>
          </div>
        </el-col>
      </el-row>
    </div>
  </div>
</template>

<style scoped lang="scss">
.app_login {
  width: 100vw;
  height: 100vh;
  background-image: url("/public/bg.jpg");
  background-repeat: no-repeat;
  background-size: cover;

  .login_top {
    padding-left: 10px;
    width: 100%;
    height: 40px; /* 调整合适的高度 */
    display: flex;
    align-items: center; /* 在垂直方向上居中 */
    background: linear-gradient(135deg, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.3));

    .top_logo {
      width: 40px;
      height: 40px;
    }

    .top_title {
      font-size: 24px; /* 调整字号 */
      font-family: '仿宋'; /* 使用更好看的字体 */
      color: #000; /* 设置字体颜色 */
      font-weight: bolder;
      text-align: center;
      line-height: 1.2; /* 调整行高，使文本更清晰易读 */
      letter-spacing: 1px; /* 调整字符间距，增加可读性 */
    }
  }

  .login_main {
    width: 100vw;
    height: calc(100vh - 40px);
    display: flex;
    justify-content: center;
    align-items: center;

    .main_form {
      width: 500px;
    }
  }
}
</style>
